from gevent import monkey
import socket
import re
import gevent

# 让gevent识别普通的耗时操作，并适时的切换进程
monkey.patch_all()


def request_handler(new_client_socket):
    request_data = new_client_socket.recv(1024)
    if not request_data:
        print("客户端断开链接")
        new_client_socket.close()
        return

    request_data_str = request_data.decode()
    request_list = request_data_str.split("\r\n")
    ret = re.search(r"\s(.*)\s", request_list[0])
    if not ret:
        print("⽤户请求报⽂格式错误!")
        new_client_socket.close()
        return
    # 得到路径
    path_info = ret.group(1)
    print("接收到⽤户请求：", path_info)
    # 设置默认请求⻚⾯为 index.html
    if path_info == "/":
        path_info = "/index.html"

    response_header = "Server:Python-Web1.0\r\n"
    response_blank = "\r\n"

    try:
        # 读取指定路径⽂件，并且返回
        with open("static" + path_info, "rb") as file:
            # 读取⽂件的⼆进制数据
            response_content = file.read()

    except Exception as e:
        # 开始拼接响应数据
        response_line = "HTTP/1.1 404 Not Found\r\n"
        response_content = "Error !!! %s" % str(e)
        response_content = response_content.encode()
    else:
        # 开始拼接响应数据
        response_line = "HTTP/1.1 200 OK\r\n"

    # 拼接响应头
    response_data = (response_line + response_header + response_blank).encode() + response_content
    # 发送数据
    new_client_socket.send(response_data)
    # 关闭socket
    new_client_socket.close()


def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定IP 和端⼝
    tcp_server_socket.bind(("", 8080))
    # 设置套接字为被动套接字，主要接收客户端链
    tcp_server_socket.listen(128)

    while True:
        # 接受客户端链接
        new_client_socket, ip_port = tcp_server_socket.accept()
        print("[新客户端上线]", ip_port)
        # 相应客户端请求，发送数据给客户端
        # request_handler(new_client_socket)
        # 使⽤gevent协程处理客户端请求
        g1 = gevent.spawn(request_handler, new_client_socket)
        # 因为服务器⼀直在while True 不会退出，所以此处不⽤join⼀次
        # g1.join()


if __name__ == '__main__':
    main()
